﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using ShareContent;
namespace AncientEmpires_025_132
{
    public class MapWithCell
    {
        #region Các thuộc tính của map.
        // Ma trận các ô trong bản đồ.
        private Cell[,] _cells;

        public Cell[,] Cells
        {
            get { return _cells; }
            set { _cells = value; }
        }

        // Số hàng trong ma trận (trong bản đồ)
        private static int _nrows;
        public static int Nrows
        {
            get { return _nrows; }
            set { _nrows = value; }
        }

        // Số cột trong ma trận (trong bản đồ)
        private int _ncols;
        public int Ncols
        {
            get { return _ncols; }
            set { _ncols = value; }
        }

        // Cell hiệu ứng các ô đi được khi nhân vật được chọn.
        private ListCellsMoveEffect _listCellsEffect;
        public ListCellsMoveEffect ListCellsEffect
        {
            get { return _listCellsEffect; }
            set { _listCellsEffect = value; }
        }

        // Các building trong map. Sẽ được hiển thị ra map.
        private List<Building> _listBuilding;
        public List<Building> ListBuilding
        {
            get { return _listBuilding; }
            set { _listBuilding = value; }
        }

        // Thông tin các building có trong file xml.
        private List<BuildingOfMap> _listInfoAllBuilding;
        public List<BuildingOfMap> ListInfoAllBuilding
        {
            get { return _listInfoAllBuilding; }
            set { _listInfoAllBuilding = value; }
        }

        private List<Character> _listCharacter;
        public List<Character> ListCharacter
        {
            get { return _listCharacter; }
            set { _listCharacter = value; }
        }

        //
        private int[,] label;
        public int[,] Label
        {
            get { return label; }
            set { label = value; }
        }

        // Lấy kích thước của màn hình.
        private GameWindow _window;
        public GameWindow Window
        {
            get { return _window; }
            set { _window = value; }
        }

        // Danh sách tên các map.
        private ListMaps _listInfoMaps;
        public ListMaps ListInfoMaps
        {
            get { return _listInfoMaps; }
            set { _listInfoMaps = value; }
        }

        private List<NationName> listNationName;
        public List<NationName> ListNationName
        {
            get { return listNationName; }
            set { listNationName = value; }
        }

        private List<TeamName> listTeamName;
        public List<TeamName> ListTeamName
        {
            get { return listTeamName; }
            set { listTeamName = value; }
        }

        private List<Vector2> listCellCanHit;
        public List<Vector2> ListCellCanHit
        {
            get { return listCellCanHit; }
            set { listCellCanHit = value; }
        }

        private Character currentSelectCharacter;
        public Character CurrentSelectCharacter
        {
            get { return currentSelectCharacter; }
            set { currentSelectCharacter = value; }
        }
        #endregion

        // kích thước của cell khi vẽ lên bản đồ
        public static int CELL_WIDTH = 35;
        public static int CELL_HEIGHT = 35;
        public HuongDiChuyen huongDiChuyen;
        public MouseState preMouseSate = Mouse.GetState();

        private List<Vector2> _listIndexCellEffect;
        public List<Vector2> ListIndexCellEffect
        {
            get { return _listIndexCellEffect; }
            set { _listIndexCellEffect = value; }
        }

        private ContentManager _myContent;
        public ContentManager MyContent
        {
            get { return _myContent; }
            set { _myContent = value; }
        }

        private MyMouse mState;
        public MyMouse MState
        {
            get { return mState; }
            set { mState = value; }
        }

        

        #region Các sự kiện phát sinh ra
        //Thay đổi list building.
        public delegate void EvenHandleChangeListBuilding(object map);
        public event EvenHandleChangeListBuilding EventChangeListBuilding;
        //Thay đổi list character.
        public delegate void EvenHandleChangeListCharacter(object map);
        public event EvenHandleChangeListCharacter EventChangeListCharacter;

        public delegate void EventHandlEndturnNation();
        public event EventHandlEndturnNation EndturnNation;

        // Update text cho panegame.
        public delegate void EventHandleUpdateTextPanel();
        public event EventHandleUpdateTextPanel EventUpdateTextPanel;

        // Event back to main menu
        public delegate void EventHandleBackMainMenu();
        public event EventHandleBackMainMenu EventBackMainMenu;

        // Event exit game
        public delegate void EventHandleExitGame();
        public event EventHandleExitGame EventExitGame;

        // Event exit game
        public delegate void EventHandlePauseGame();
        public event EventHandlePauseGame EventPauseGame;

        // Event exit game
        public delegate void EventHandleResumeGame();
        public event EventHandleResumeGame EventResumeGame;

        // Event buy character.
        public delegate bool EventHandleBuyCharacter(NationName nationName, CharacterName characterName);
        public event EventHandleBuyCharacter EventBuyCharacter;
        #endregion

        #region Xử lý các sự kiện khi map nhận được
        //Sự kiện kết thúc lượt đi của 1 nation
        void PanelGame_EventEndturn()
        {
            EndturnNation();
        }

        void PanelGame_EventUpdateText()
        {
            EventUpdateTextPanel();
        }
        // Xử lý sự kiện khi nhân vật được chọn.
        public void SelectedCharacter(Character character)
        {
            SetCellEffect(character);
            PanelGameGetTextFromCharacter(character);
            this.MState.GameMouse = MyMouseState.ChooseCharacter;
            this.CurrentSelectCharacter = character;
        }

        // Xư lý sự kiện khi nhân vật được bỏ chọn.
        public void UnSelectedCharacter()
        {
            ListCellsEffect.ListCells.Clear();
            PanelGame.AvatarCurrentCharacter.TextureCurrent = null;
            this.MState.GameMouse = MyMouseState.Normal;
            this.CurrentSelectCharacter = null;
        }

        // Xử lý sự kiện khi nhân vật bắt đầu di chuyển.
        public void StartMovingCharacter(Character character)
        {
            for (int i = 0; i < ListIndexCellEffect.Count; i++)
            {
                if (ListIndexCellEffect[i] == this.IndexCellCurrentIsSelected)
                {
                    character.ListMoving = BFSAlgorithm(character.PositionInMatrix, this.IndexCellCurrentIsSelected);

                    break;
                }

            }
            /// Nếu click cell ngoài các cell mà nhân vật có thể đi thì xem như là bỏ chọn nhân vật.
            ListCellsEffect.ListCells.Clear();
            PanelGame.AvatarCurrentCharacter.TextureCurrent = null;
            this.MState.GameMouse = MyMouseState.Normal;
            
            // Kiểm tra nhân vật đánh nhân vật
            for (int i = 0; i < ListCellCanHit.Count; i++)
            {
                if (ListCellCanHit[i] == IndexCellCurrentIsSelected)
                {
                    for (int j = 0; j < ListCharacter.Count; j++)
                    {
                        if (CurrentSelectCharacter == ListCharacter[j])
                        {
                            ListCharacter[j].IsStartSkill = true;
                            ListCharacter[j].MySkill.InitTopLeft(Cells[(int)IndexCellCurrentIsSelected.X, (int)IndexCellCurrentIsSelected.Y].ListSprites[0].TopLeft);
                            this.CurrentSelectCharacter = null;
                            ListCellCanHit.Clear();
                            return;
                        }
                    }
                }
            }

            this.CurrentSelectCharacter = null;
        }
        
        // Xử lý sự kiện khi nhân vật kết thúc 1 lượt đi.
        public void EndMovingCharacter(Character character)
        {
            foreach (Character ch in ListCharacter)
            {
                if (character == ch)
                {
                    ListCellCanHit = BFSAlgorithmToHit(character.PositionInMatrix, character.MyIndexNation, GetIndexTeam(character.MyNationName));
                    if (ListCellCanHit.Count > 0)
                    {
                        //ListIndexCellEffect = BFSAlgorithm(this.IndexCellCurrentIsSelected, character.MaxDistance);
                        //ListCellsEffect.InitCellsEffect(ListIndexCellEffect);
                        ListCellsEffect.AppendCellsEffect(ListCellCanHit);
                        PanelGameGetTextFromCharacter(character);
                        ch.IsEndTurn = false;
                        
                        this.CurrentSelectCharacter = ch;
                    }
                    else
                    {
                        ch.MySound.Stop();
                        ch.IsEndTurn = true;
                        this.CurrentSelectCharacter = null;
                    }
                    BuildingOccupy(ch);
                    break;
                }
            }
        }
        public void BuildingOccupy(Character character)
        {
            List<Vector2> listIndex = GetFourSideCells(character.PositionInMatrix);
            for (int i = 0; i < listIndex.Count; i++)
            {
                for (int j = 0; j < ListBuilding.Count; j++)
                {
                    for (int k = 0; k < ListBuilding[j].ListIndexCellUse.Count; k++)
                    {
                        if (listIndex[i] == ListBuilding[j].ListIndexCellUse[k])
                        {
                            ListBuilding[j].MyNationName = character.MyNationName;
                            EventChangeListBuilding(this);
                        }
                    }
                }
            }
        }

        // Xử lý sự kiện khi nhân vật kết thúc đánh.
        public void EndHurtCharacter()
        {
            for (int i = 0; i < ListCharacter.Count; i++)
            {
                ListCharacter[i].MySound.Stop();
            }
        }

        // Xứ lý sự kiện khi nhân vật chết.
        public void DeadCharacter(Character character)
        {
            for (int i = 0; i < ListCharacter.Count; i++ )
            {
                if (character == ListCharacter[i])
                {
                    ListCharacter.RemoveAt(i);
                    EventChangeListCharacter(this);
                    return;
                }
            }
        }

        // Xử lý sự kiện khi click chuột vào 1 cell trong ma trận các cell.
        public void SelectedCell(Vector2 indexMatrix)
        {
            IndexCellCurrentIsSelected = indexMatrix;
            if (CurrentSelectCharacter != null)
            {
                for (int i = 0; i < ListCellCanHit.Count; i++)
                {
                    if (ListCellCanHit[i] == IndexCellCurrentIsSelected)
                    {
                        for (int j = 0; j < ListCharacter.Count; j++)
                        {
                            
                            if (CurrentSelectCharacter == ListCharacter[j])
                            {

                                ListCharacter[j].IsStartSkill = true;
                                ListCharacter[j].MySkill.InitTopLeft(Cells[(int)IndexCellCurrentIsSelected.X, (int)IndexCellCurrentIsSelected.Y].ListSprites[0].TopLeft);
                                this.CurrentSelectCharacter = null;
                                ListCellCanHit.Clear();
                                ListIndexCellEffect.Clear();
                                ListCellsEffect.ListCells.Clear();
                                ListCharacter[j].MySound.IEffect = 1;
                                ListCharacter[j].MySound.PlayEffect(Volume.MyVolume);
                                int damage = ListCharacter[j].GetRandomDamage();
                                for (int k = 0; k < ListCharacter.Count; k++)
                                {
                                    if (IndexCellCurrentIsSelected == ListCharacter[k].PositionInMatrix)
                                    {
                                        ListCharacter[k].MySound.IEffect = 2;
                                        ListCharacter[k].MySound.PlayEffect(Volume.MyVolume);
                                        ListCharacter[k].HealthPoints -= damage;
                                        ListCharacter[k].HealthPoints += ListCharacter[k].Defense;
                                    }
                                }
                                return;
                            }
                            
                        }
                    }
                }
            }
        }

        // Xử lý sự kiện khi click chuột chọn castle.
        public void SelectCastle()
        {
            for (int i = 0; i < PanelGame.ListBuyAvatarCharater.Count; i++)
            {
                PanelGame.ListBuyAvatarCharater[i].IsHide = false;
                PanelGame.BtnBuy.IsHide = false;
            }
        }
        public void UnSelectCastle(Building building, Vector2 position)
        {
            if (this.GetCellFromPoint(position) == Vector2.Zero)
            {
                building.IsSelected = true;
                building.NumberOfClick = 0;
                return;
            }
            for (int i = 0; i < PanelGame.ListBuyAvatarCharater.Count; i++)
            {
                PanelGame.BtnBuy.IsHide = true;
                PanelGame.ListBuyAvatarCharater[i].IsHide = true;
                PanelGame.ListBuyAvatarCharater[i].IsSelected = false;
            }
        }

        // Xử lý sự kiện mua 1 character.
        void PanelGame_EventBuy(CharacterName characterName)
        {
            foreach (Building castle in ListBuilding)
            {

                if (castle is Castle && castle.MyNationName == CurrentCircle.NationCurrent)
                {
                    if (EventBuyCharacter(CurrentCircle.NationCurrent, characterName))
                    {
                        ListCharacter.Add(castle.NewCharacter(this.MyContent, characterName, castle.ListSprites[0].Position, -castle.ListSprites[0].Position, castle.MyNationName));
                        int index = ListCharacter.Count - 1;
                        ListCharacter[index].Cells = this.Cells;
                        ListCharacter[index].SetViewPort(CELL_WIDTH, CELL_HEIGHT);
                        ListCharacter[index].EventSelected += new Character.EventHandleSelected(SelectedCharacter);
                        ListCharacter[index].EventUnSelected += new Character.EventHandleUnSelected(UnSelectedCharacter);
                        ListCharacter[index].EventStartMoving += new Character.EventHandleStartMoving(StartMovingCharacter);
                        ListCharacter[index].EventEndMoving += new Character.EventHandlEndMoving(EndMovingCharacter);
                        ListCharacter[index].EventEndHurt += new Character.EventHandleEndHurt(EndHurtCharacter);
                        ListCharacter[index].EventDead += new Character.EventHandleDead(DeadCharacter);
                        EventChangeListCharacter(this);
                    }
                }
            }
        }

        // Proccess for back to main menu
        void PanelGame_EventBackMainMenu()
        {
            EventBackMainMenu();
        }

        // Proccess for back to main menu
        void PanelGame_EventExitGame()
        {
            EventExitGame();
        }

        // Proccess for back to main menu
        void PanelGame_EventPauseGame()
        {
            EventPauseGame();
        }

        // Proccess for back to main menu
        void PanelGame_EventResumeGame()
        {
            EventResumeGame();
        }
        
        #endregion
        public void PanelGameGetTextFromCharacter(Character character)
        {
            PanelGame.AvatarCurrentCharacter.TextureCurrent = character.TextureAvatar;
            PanelGame.AvatarCurrentCharacter.CharacterName = character.Name.ToString();
            PanelGame.AvatarCurrentCharacter.Damage = character.MinDamage.ToString() + "-" + character.MaxDamage;
            PanelGame.AvatarCurrentCharacter.Defense = character.Defense.ToString();
            PanelGame.AvatarCurrentCharacter.HealthPoints = character.HealthPoints.ToString();
            PanelGame.AvatarCurrentCharacter.Level = character.Level.ToString();
        }

        

        //Thông tin toàn bộ của map hiện tại.
        private Map _infoMapCurrent;
        public Map InfoMapCurrent
        {
            get { return _infoMapCurrent; }
            set { _infoMapCurrent = value; }
        }

        private OptionPanel _panelGame;
        public OptionPanel PanelGame
        {
            get { return _panelGame; }
            set { _panelGame = value; }
        }
        private InfoOptionPanel _infoPanel;
        public InfoOptionPanel InfoPanel
        {
            get { return _infoPanel; }
            set { _infoPanel = value; }
        }

        private Vector2 _indexCellCurrentIsSelected;
        public Vector2 IndexCellCurrentIsSelected
        {
            get { return _indexCellCurrentIsSelected; }
            set { _indexCellCurrentIsSelected = value; }
        }
        public MapWithCell(ContentManager content, GameWindow window, string strXML)
        {
            MyContent = content;
            this.Window = window;
            ListInfoMaps = content.Load<ListMaps>(strXML);
            InfoPanel = content.Load<InfoOptionPanel>(ListInfoMaps.strInfoOptionPanel);
            
            PanelGame = new OptionPanel(content, InfoPanel);
            PanelGame.EventEndturn += new OptionPanel.EventHandleEndturn(PanelGame_EventEndturn);
            PanelGame.EventUpdateText += new OptionPanel.EventHandleUpdateText(PanelGame_EventUpdateText);
            PanelGame.EventBuy += new OptionPanel.EventHandleBuyCharacter(PanelGame_EventBuy);
            PanelGame.EventBackMainMenu += new OptionPanel.EventHandleBackMainMenu(PanelGame_EventBackMainMenu);
            PanelGame.EventExitGame += new OptionPanel.EventHandleExitGame(PanelGame_EventExitGame);
            PanelGame.EventPauseGame += new OptionPanel.EventHandlePauseGame(PanelGame_EventPauseGame);
            PanelGame.EventResumeGame += new OptionPanel.EventHandleResumeGame(PanelGame_EventResumeGame);

            IndexCellCurrentIsSelected = new Vector2();
            ListNationName = new List<NationName>();
            ListTeamName = new List<TeamName>();
            ListCellCanHit = new List<Vector2>();
        }

        public void CaptureEventFromCharacter()
        {
            for (int i = 0; i < this.ListCharacter.Count; i++)
            {
                ListCharacter[i].EventSelected += new Character.EventHandleSelected(SelectedCharacter);
                ListCharacter[i].EventUnSelected += new Character.EventHandleUnSelected(UnSelectedCharacter);
                ListCharacter[i].EventStartMoving += new Character.EventHandleStartMoving(StartMovingCharacter);
                ListCharacter[i].EventEndMoving +=new Character.EventHandlEndMoving(EndMovingCharacter);
                ListCharacter[i].EventEndHurt +=new Character.EventHandleEndHurt(EndHurtCharacter);
                ListCharacter[i].EventDead += new Character.EventHandleDead(DeadCharacter);
            }
        }
        public void CaptureEvenFromBuilding()
        {
            for (int i = 0; i < this.ListBuilding.Count; i++)
            {
                if (ListBuilding[i] is Castle)
                {
                    ListBuilding[i].EventSelected += new Building.EventHandleSelected(SelectCastle);
                    ListBuilding[i].EventUnSelected += new Building.EventHandUnselected(UnSelectCastle);
                }
            }
        }
        public void InitNewMap(ContentManager content, GameWindow window, string nameMapCurrent)
        {
            
            ListCharacter = new List<Character>();
            ListIndexCellEffect = new List<Vector2>();
            
            string stringxml = "";
            for (int i = 0; i < ListInfoMaps.listInfoStringMap.Count; i++)
            {
                if (ListInfoMaps.listInfoStringMap[i].NameMap == nameMapCurrent)
                {
                    stringxml = ListInfoMaps.listInfoStringMap[i].StringXMLMAP;
                    break;
                }
            }
            InfoMapCurrent = content.Load<Map>(stringxml);
            ListInfoAllBuilding = InfoMapCurrent.listBuildings;
            
            //Ma trận các chỉ số của cell.
            int[,] matrixIndexCells = new int[(int)InfoMapCurrent.dimensionMap.X, (int)InfoMapCurrent.dimensionMap.Y];

            for (int i = 0; i < (int)InfoMapCurrent.dimensionMap.X; i++)
            {
                for (int j = 0; j < (int)InfoMapCurrent.dimensionMap.Y; j++)
                {
                    matrixIndexCells[i, j] = InfoMapCurrent.matrixCells[i * (int)InfoMapCurrent.dimensionMap.Y + j];
                }
            }

            string[] strtexture = new string[InfoMapCurrent.typeCell.Count];
            for (int i = 0; i < InfoMapCurrent.typeCell.Count; i++)
            {
                strtexture[i] = InfoMapCurrent.typeCell[i];
            }

            _nrows = (int)InfoMapCurrent.dimensionMap.X;
            _ncols = (int)InfoMapCurrent.dimensionMap.Y;
            label = new int[_nrows, _ncols];
            // new celleffect
            ListCellsEffect = new ListCellsMoveEffect(content, InfoMapCurrent.cellEffect.ToArray(), new Vector2(CELL_WIDTH, CELL_HEIGHT));
            
            // new cells
            Cells = new Cell[_nrows, _ncols];

            for (int i = 0; i < Nrows; i++)
            {
                for (int j = 0; j < Ncols; j++)
                {
                    label[i, j] = -1;
                    Cells[i, j] = new Cell(content, strtexture[matrixIndexCells[i, j]],
                                        new Vector2(j * CELL_WIDTH, i * CELL_HEIGHT), new Vector2(CELL_WIDTH, CELL_HEIGHT), 
                                        new Vector2(-j * CELL_WIDTH, -i * CELL_HEIGHT), new Vector2(i,j));
                    Cells[i, j].IsMoveable = GetIsCellMoveable(InfoMapCurrent.cellNotMoveable, matrixIndexCells[i, j]);
                    Cells[i, j].IsUsed = IndexNation.Available;
                    Cells[i, j].EventSelected += new Cell.EventHandleSelected(SelectedCell);  
                }
            }
            Cells[0, 0].ListSprites[0].TopLeft = new Vector2(0, 0);
            ListCellsEffect.Cells = Cells;
        }
        public void SetCellUsed(List<Vector2> listCellUsed, int indexNation)
        {
            for (int i = 0; i < listCellUsed.Count; i++)
            {
                Cells[(int)listCellUsed[i].X, (int)listCellUsed[i].Y].IsUsed = indexNation;
            }
        }
        public bool GetIsCellMoveable(int[] matrix, int index)
        {
            for (int i = 0; i < matrix.Length; i++)
            {
                if (index == matrix[i])
                {
                    return false;
                }
            }
            return true;
        }
        public Vector2 GetCellFromPoint(Vector2 point)
        {
            Vector2 index = point;
            index = index - PanelGame.SizePanel;
            if (index.X < 0)
            {
                return Vector2.Zero;
            }
            index.X = index.Y / CELL_HEIGHT;
            index.Y = index.X / CELL_WIDTH;
            return index;
        }
        public bool CheckCellValid(Vector2 poscell)
        {
            if (this.Cells[(int)poscell.X, (int)poscell.Y].IsMoveable && Cells[(int)poscell.X, (int)poscell.Y].IsUsed == IndexNation.Available)
            {
                return true;
            }
            return false;
        }
        public bool CheckCellHit(Vector2 poscell, int indexNation, int indexTeam)
        {
            int cellState = Cells[(int)poscell.X, (int)poscell.Y].IsUsed;
            if (this.Cells[(int)poscell.X, (int)poscell.Y].IsMoveable && cellState != IndexNation.Available && 
                                                                         cellState != IndexNation.NoneNation &&
                                                                         cellState != indexNation &&
                                                                         indexTeam != GetIndexTeamFromIndexNation(cellState)
                )
            {
                for (int i = 0; i < ListCharacter.Count; i++)
                {
                    if (ListCharacter[i].MyNationName != CurrentCircle.NationCurrent && ListCharacter[i].PositionInMatrix == poscell)
                    {
                        return true;
                    }
                }
                return false;
            }
            return false;
        }

        public int GetIndexTeamFromIndexNation(int indexNation)
        {

            if (indexNation == IndexNation.Available)
            {
                return GetIndexTeam(NationName.None);
            }
            if (indexNation == IndexNation.NoneNation)
            {
                return GetIndexTeam(NationName.None);
            }
            if (indexNation == IndexNation.RedNation)
            {
                return GetIndexTeam(NationName.Red);
            }
            if (indexNation == IndexNation.GreenNation)
            {
                return GetIndexTeam(NationName.Green);
            }
            if (indexNation == IndexNation.BlueNation)
            {
                return GetIndexTeam(NationName.Blue);
            }
            if (indexNation == IndexNation.BlackNation)
            {
                return GetIndexTeam(NationName.Black);
            }
            return 0;
        }
        public int GetIndexTeam(NationName nation)
        { 
            for (int i = 0; i < ListNationName.Count; i++)
                {
                    if (listNationName[i] == nation)
                    {
                        switch (ListTeamName[i])
                        {
                            case TeamName.Team1:
                                return 1;
                            case TeamName.Team2:
                                return 2;
                            case TeamName.Team3:
                                return 3;
                            case TeamName.Team4:
                                return 4;
                        }
                    }
                }
            return 0;
        }


        public List<Vector2> GetFourSideCells(Vector2 pos)
        {
            List<Vector2> listcell = new List<Vector2>();
            if (pos.X > 0)
            {
                listcell.Add(new Vector2(pos.X - 1, pos.Y));
            }
            if (pos.Y > 0)
            {
                listcell.Add(new Vector2(pos.X, pos.Y - 1));
            }
            if (pos.Y < _ncols - 1)
            {
                listcell.Add(new Vector2(pos.X, pos.Y + 1));
            }
            if (pos.X < _nrows - 1)
            {
                listcell.Add(new Vector2(pos.X + 1, pos.Y));
            }

            return listcell;
        }
        public List<Vector2> GetListMove(Vector2 posCell)
        {
            List<Vector2> list = new List<Vector2>();
            list.Add(posCell);
            int count = label[(int)posCell.X, (int)posCell.Y];
            Vector2 temp = new Vector2();
            while (count > 0)
            {
                count--;
                if (posCell.X > 0 && count == label[(int)posCell.X - 1, (int)posCell.Y])
                {
                    temp = new Vector2(posCell.X - 1, posCell.Y);
                    list.Add(temp);
                    posCell = temp;
                }
                else
                {
                    if (posCell.Y > 0 && count == label[(int)posCell.X, (int)posCell.Y - 1])
                    {
                        temp = new Vector2(posCell.X, posCell.Y - 1);
                        list.Add(temp);
                        posCell = temp;
                    }
                    else
                    {
                        if (posCell.Y < _ncols - 1 && count == label[(int)posCell.X, (int)posCell.Y + 1])
                        {
                            temp = new Vector2(posCell.X, posCell.Y + 1);
                            list.Add(temp);
                            posCell = temp;
                        }
                        else
                        {
                            if (posCell.X < _nrows - 1 && count == label[(int)posCell.X + 1, (int)posCell.Y])
                            {
                                temp = new Vector2(posCell.X + 1, posCell.Y);
                                list.Add(temp);
                                posCell = temp;
                            }
                        }
                    }
                }

            }
            List<Vector2> templist = new List<Vector2>();
            for (int i = list.Count - 1; i >= 0; i--)
            {
                templist.Add(list[i]);
            }
            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    label[i, j] = -1;
                }
            }
            return templist;
        }
        public List<Vector2> BFSAlgorithm(Vector2 first, Vector2 last)
        {
            for (int i = 0; i < Nrows; i++)
            {
                for (int j = 0; j < Ncols; j++)
                {
                    Label[i, j] = -1;
                }
            }

            List<Vector2> list = new List<Vector2>();
            List<Vector2> listcell = new List<Vector2>();
            list.Add(first);
            label[(int)first.X, (int)first.Y] = 0;
            
            bool flag = true;
            int count = 0;
            while (flag)
            {
                flag = false;
                count++;
                for (int i = 0; i < list.Count; i++)
                {
                    listcell = GetFourSideCells(list[i]);
                    for (int j = 0; j < listcell.Count; j++)
                    {
                        if(label[(int)listcell[j].X, (int)listcell[j].Y] == -1 && CheckCellValid(new Vector2(listcell[j].X, listcell[j].Y)))
                        {
                            label[(int)listcell[j].X, (int)listcell[j].Y] = count;
                            flag = true;
                            if (last == listcell[j])
                            {
                                return GetListMove(last);
                            }
                        }
                    }
                }
                list.Clear();
                for (int i = 0; i < _nrows; i++)
                {
                    for (int j = 0; j < _ncols; j++)
                    {
                        if (label[i, j] == count)
                        {
                            flag = true;
                            list.Add(new Vector2(i, j));
                        }
                    }
                }
            }
            list.Clear();
            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    label[i, j] = -1;
                }
            }
            return list;
        }
        public List<Vector2> BFSAlgorithm(Vector2 first, int maxDistance)
        {
            // Clear label
            for (int i = 0; i < Nrows; i++)
            {
                for (int j = 0; j < Ncols; j++)
                {
                    Label[i, j] = -1;
                }
            }
            //////////
            List<Vector2> listkq = new List<Vector2>();
            List<Vector2> list = new List<Vector2>();
            List<Vector2> listcell = new List<Vector2>();
            list.Add(first);
            label[(int)first.X, (int)first.Y] = 0;

            bool flag = true;
            int count = 0;
            while (flag)
            {
                flag = false;
                count++;
                for (int i = 0; i < list.Count; i++)
                {
                    listcell = GetFourSideCells(list[i]);
                    
                    for (int j = 0; j < listcell.Count; j++)
                    {
                        if (label[(int)listcell[j].X, (int)listcell[j].Y] == -1 && CheckCellValid(new Vector2(listcell[j].X, listcell[j].Y)))
                        {
                            label[(int)listcell[j].X, (int)listcell[j].Y] = count;
                            flag = true;
                            listkq.Add(new Vector2((int)listcell[j].X, (int)listcell[j].Y));
                        }
                    }
                    
                }
                if (count == maxDistance)
                {
                    return listkq;
                }
                list.Clear();
                for (int i = 0; i < _nrows; i++)
                {
                    for (int j = 0; j < _ncols; j++)
                    {
                        if (label[i, j] == count)
                        {
                            flag = true;
                            list.Add(new Vector2(i, j));
                        }
                    }
                }
            }
            list.Clear();
            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    label[i, j] = -1;
                }
            }
            return listkq;
        }
        public List<Vector2> BFSAlgorithmToHit(Vector2 posCell, int indexNation, int indexTeam)
        {
            // Clear label
            for (int i = 0; i < Nrows; i++)
            {
                for (int j = 0; j < Ncols; j++)
                {
                    Label[i, j] = -1;
                }
            }
            //////////
            List<Vector2> listkq = new List<Vector2>();
            List<Vector2> list = new List<Vector2>();
            List<Vector2> listcell = new List<Vector2>();
            list.Add(posCell);
            label[(int)posCell.X, (int)posCell.Y] = 0;

            bool flag = true;
            int count = 0;
            while (flag)
            {
                flag = false;
                count++;
                for (int i = 0; i < list.Count; i++)
                {
                    listcell = GetFourSideCells(list[i]);

                    for (int j = 0; j < listcell.Count; j++)
                    {
                        if (label[(int)listcell[j].X, (int)listcell[j].Y] == -1)
                        {   
                            if(CheckCellHit(new Vector2(listcell[j].X, listcell[j].Y), indexNation, indexTeam))
                                listkq.Add(new Vector2((int)listcell[j].X, (int)listcell[j].Y));
                        
                            label[(int)listcell[j].X, (int)listcell[j].Y] = count;
                            flag = true;
                        }
                    }

                }
                if (count == 2)
                {
                    return listkq;
                }
                list.Clear();
                for (int i = 0; i < _nrows; i++)
                {
                    for (int j = 0; j < _ncols; j++)
                    {
                        if (label[i, j] == count)
                        {
                            flag = true;
                            list.Add(new Vector2(i, j));
                        }
                    }
                }
            }
            list.Clear();
            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    label[i, j] = -1;
                }
            }
            return listkq;
        }

        // Thay đổi vị trí tọa độ trong màn hình thành vị trí trong ma trận của map.
        public Vector2 PositionToIndexInMatrix(Vector2 position)
        {
            Vector2 index = new Vector2();
            Vector2 tempTopLeft = position;
            return index;
        }
        // Thay đổi vị trí trong ma trận của map thành vị trí tọa độ trong màn hình.
        public Vector2 IndexInMatrixToPosition(Vector2 indexInMatrix)
        {
            Vector2 position = new Vector2();
            return position;
        }

        public void SetTopLeftMap(Vector2 topleft)
        {
            Vector2 temp = topleft - Cells[0, 0].ListSprites[0].TopLeft;
            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    Cells[i, j].ListSprites[0].TopLeft += temp;
                }
            }
            for (int i = 0; i < ListBuilding.Count; i++)
            {
                ListBuilding[i].ListSprites[0].TopLeft += temp;
            }
            for (int i = 0; i < ListCharacter.Count; i++)
            {
                for (int j = 0; j < ListCharacter[i].ListSprites.Count; j++)
                {
                    ListCharacter[i].ListSprites[j].TopLeft += temp;
                    
                }
                ListCharacter[i].MySkill.SetTopLeft(temp);
            }
            ListCellsEffect.SetTopLeft(temp);
            
        }
        public void SetTopLeftCells()
        {
            Vector2 topleftmap = Cells[0, 0].ListSprites[0].TopLeft;
            switch (huongDiChuyen)
            {
                case HuongDiChuyen.TraiQuaPhai:
                    if (topleftmap.X + UnitGameEntity.UnitMoveOfCellFast + Window.ClientBounds.Width <= CELL_WIDTH * Ncols)
                    {
                        topleftmap.X += UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.PhaiQuaTrai:
                    if (topleftmap.X - UnitGameEntity.UnitMoveOfCellFast >= -this.PanelGame.SizePanel.X)
                    {
                        topleftmap.X -= UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.DuoiLenTren:
                    if (topleftmap.Y - UnitGameEntity.UnitMoveOfCellFast >= 0)
                    {
                        topleftmap.Y -= UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.TrenXuongDuoi:
                    if (topleftmap.Y + UnitGameEntity.UnitMoveOfCellFast + Window.ClientBounds.Height <= CELL_HEIGHT * Nrows)
                    {
                        topleftmap.Y += UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.CheoTraiQuaPhaiDuoiLen:
                    if (topleftmap.X + UnitGameEntity.UnitMoveOfCellFast + Window.ClientBounds.Width <= CELL_WIDTH * Ncols)
                    {
                        topleftmap.X += UnitGameEntity.UnitMoveOfCellFast;
                    }
                    if (topleftmap.Y - UnitGameEntity.UnitMoveOfCellFast >= 0)
                    {
                        topleftmap.Y -= UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.CheoTraiQuaPhaiTrenXuong:
                    if (topleftmap.X + UnitGameEntity.UnitMoveOfCellFast + Window.ClientBounds.Width <= CELL_WIDTH * Ncols)
                    {
                        topleftmap.X += UnitGameEntity.UnitMoveOfCellFast;
                    }
                    if (topleftmap.Y + UnitGameEntity.UnitMoveOfCellFast + Window.ClientBounds.Height <= CELL_HEIGHT * Nrows)
                    {
                        topleftmap.Y += UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.CheoPhaiQuaTraiDuoiLen:
                    if (topleftmap.X - UnitGameEntity.UnitMoveOfCellFast >= -this.PanelGame.SizePanel.X)
                    {
                        topleftmap.X -= UnitGameEntity.UnitMoveOfCellFast;
                    }
                    if (topleftmap.Y - UnitGameEntity.UnitMoveOfCellFast >= 0)
                    {
                        topleftmap.Y -= UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
                case HuongDiChuyen.CheoPhaiQuaTraiTrenXuong:
                    if (topleftmap.X - UnitGameEntity.UnitMoveOfCellFast >= -this.PanelGame.SizePanel.X)
                    {
                        topleftmap.X -= UnitGameEntity.UnitMoveOfCellFast;
                    }
                    if (topleftmap.Y + UnitGameEntity.UnitMoveOfCellFast + Window.ClientBounds.Height <= CELL_HEIGHT * Nrows)
                    {
                        topleftmap.Y += UnitGameEntity.UnitMoveOfCellFast;
                    }
                    break;
            }

            SetTopLeftMap(topleftmap);
        }
        
        public void SetHuongDiChuyenMouse(MouseState ms)
        {
            if (ms.X < preMouseSate.X && ms.Y < preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.CheoPhaiQuaTraiDuoiLen;
            }
            if (ms.X < preMouseSate.X && ms.Y > preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.CheoPhaiQuaTraiTrenXuong;
            }

            if (ms.X < preMouseSate.X && ms.Y == preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.PhaiQuaTrai;
            }

            if (ms.X > preMouseSate.X && ms.Y == preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.TraiQuaPhai;
            }

            if (ms.X > preMouseSate.X && ms.Y < preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.CheoTraiQuaPhaiDuoiLen;
            }

            if (ms.X > preMouseSate.X && ms.Y > preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.CheoTraiQuaPhaiTrenXuong;
            }

            if (ms.X == preMouseSate.X && ms.Y < preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.DuoiLenTren;
            }

            if (ms.X == preMouseSate.X && ms.Y > preMouseSate.Y)
            {
                huongDiChuyen = HuongDiChuyen.TrenXuongDuoi;
            }
        }
        public void SetCellEffect(Character character)
        {
            ListIndexCellEffect = BFSAlgorithm(this.IndexCellCurrentIsSelected, character.MaxDistance);
            ListCellsEffect.InitCellsEffect(ListIndexCellEffect);

            foreach (Character ch in ListCharacter)
            {
                if (character == ch)
                {
                    ListCellCanHit = BFSAlgorithmToHit(character.PositionInMatrix, character.MyIndexNation, GetIndexTeam(character.MyNationName));
                    ListCellsEffect.AppendCellsEffect(ListCellCanHit);
                    break;
                }
            }
            
        }
        public bool CheckCellMoveable(Vector2 indexCell)
        {
            return Cells[(int)indexCell.X, (int)indexCell.Y].IsMoveable;
        }

        public void Update(GameTime gametime)
        {
            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    Cells[i, j].Update(gametime);
                }
            }
            MouseState ms = Mouse.GetState();
            if (ms.RightButton == ButtonState.Pressed)
            {
                if (preMouseSate.RightButton == ButtonState.Released)
                {

                }
                else
                {
                    if (preMouseSate.RightButton == ButtonState.Pressed)
                    {
                        SetHuongDiChuyenMouse(ms);
                        SetTopLeftCells();
                    }
                }
            }
            
            //for (int i = 0; i < ListBuilding.Count; i++)
            //{
            //    ListBuilding[i].Update(gametime);
            //}

            //for (int i = 0; i < ListCharacter.Count; i++)
            //{
            //    ListCharacter[i].Update(gametime);
            //}
            //PanelGame.Update(gametime);
            //ListCellsEffect.Update(gametime);
            ListCellsEffect.Update(gametime);
            preMouseSate = ms;
        }
        public void Draw(GameTime gametime, SpriteBatch spritebatch)
        {
            UpdateForMouse();

            for (int i = 0; i < _nrows; i++)
            {
                for (int j = 0; j < _ncols; j++)
                {
                    Cells[i, j].Draw(gametime, spritebatch);
                }
            }


            //for (int i = 0; i < ListBuilding.Count; i++)
            //{
            //    ListBuilding[i].Draw(gametime, spritebatch);
            //}
            //for (int i = 0; i < ListCharacter.Count; i++)
            //{
            //    ListCharacter[i].Draw(gametime, spritebatch);
            //}
            //PanelGame.Draw(gametime, spritebatch);
            ListCellsEffect.Draw(gametime, spritebatch);
        }

        public void UpdateForMouse()
        {
            for (int i = 0; i < ListCharacter.Count; i++)
            {
                if (ListCharacter[i].IsHover)
                {
                    MState.GameMouse = MyMouseState.ChooseCharacter;
                    return;
                }
            }

            for (int i = 0; i < ListBuilding.Count; i++)
            {
                if (ListBuilding[i].IsHover)
                {
                    MState.GameMouse = MyMouseState.ChooseBuilding;
                    return;
                }
            }
            
            for (int i = 0; i < ListCellsEffect.ListCells.Count; i++)
            {
                if (ListCellsEffect.ListCells[i].IsHover && ListCellsEffect.ListCells[i].IsMove)
                {
                    MState.GameMouse = MyMouseState.Run;
                    return;
                }
            }

            for (int i = 0; i < Nrows; i++)
            {
                for (int j = 0; j < Ncols; j++)
                {
                    if (Cells[i, j].IsHover)
                    {
                        Vector2 index = new Vector2(i, j);
                        for (int k = 0; k < ListCellCanHit.Count; k++)
                        {
                            if (ListCellCanHit[k] == index)
                            {
                                MState.GameMouse = MyMouseState.Hit;
                                return;
                            }
                        }
                    }
                }
            }

            MState.GameMouse = MyMouseState.Normal;
        }
    }
}
